package cn.tedu.autoshow.resource.controller;

import cn.tedu.autoshow.commons.ex.ServiceException;
import cn.tedu.autoshow.commons.web.JsonResult;
import cn.tedu.autoshow.commons.web.ServiceCode;
import cn.tedu.autoshow.resource.vo.UploadResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Slf4j
@Api(tags = "资源上传模块")
@RestController
@RequestMapping("/resources")
public class ResourceController {

    @Value("${autoshow.upload.host}")
    private String host;
    @Value("${autoshow.upload.base-dir}")
    private String baseDir;

    @Value("${autoshow.upload.product-image.types}")
    private List<String> productImageTypes;
    @Value("${autoshow.upload.product-image.max-size}")
    private Integer productImageMaxSize;
    @Value("${autoshow.upload.product-image.dir}")
    private String productImageDir;

    @Value("${autoshow.upload.avatar-image.types}")
    private List<String> avatarImageTypes;
    @Value("${autoshow.upload.avatar-image.max-size}")
    private Integer avatarImageMaxSize;
    @Value("${autoshow.upload.avatar-image.dir}")
    private String avatarImageDir;

    @Value("${autoshow.upload.banner-image.types}")
    private List<String> bannerImageTypes;
    @Value("${autoshow.upload.banner-image.max-size}")
    private Integer bannerImageMaxSize;
    @Value("${autoshow.upload.banner-image.dir}")
    private String bannerImageDir;

    SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");

    @PostMapping("/upload/image/product")
    @ApiOperation("上传商品图片")
    public JsonResult uploadImage(
            @RequestParam("imageFile") MultipartFile file) throws Throwable{

        verify(file, productImageMaxSize, productImageTypes, "商品图片");

        UploadResult uploadResult = saveImage(file, productImageDir);

        return JsonResult.ok(uploadResult);
    }

    @PostMapping("/remove/image/product")
    @ApiOperation("删除图片")
    public JsonResult removeProduct(String url){
        removeImage(url, productImageDir);
        return JsonResult.ok();
    }

    @PostMapping("/upload/image/banner")
    @ApiOperation("上传轮播图")
    public JsonResult uploadBannerImage(
            @RequestParam("imageFile") MultipartFile file) throws Throwable{

        verify(file, bannerImageMaxSize, bannerImageTypes, "轮播图");

        UploadResult uploadResult = saveImage(file, bannerImageDir);

        return JsonResult.ok(uploadResult);
    }

    @PostMapping("/remove/image/banner")
    @ApiOperation("删除图片")
    public JsonResult removeBanner(String oldUrl){
        removeImage(oldUrl, bannerImageDir);
        return JsonResult.ok();
    }

    @PostMapping("/upload/image/avatar")
    @ApiOperation("上传头像")
    public JsonResult uploadAvatarImage(
            @RequestParam("imageFile") MultipartFile file) throws Throwable{

        verify(file, avatarImageMaxSize, avatarImageTypes, "头像");

        UploadResult uploadResult = saveImage(file, avatarImageDir);

        return JsonResult.ok(uploadResult);
    }

    @PostMapping("/remove/image/avatar")
    @ApiOperation("删除图片")
    public JsonResult removeAvatar(String oldUrl){
        removeImage(oldUrl, avatarImageDir);
        return JsonResult.ok();
    }

    /**
     * 校验图片是否合法
     * @param file
     * @param imageSize
     * @param imageTypes
     * @param name
     */
    private void verify(MultipartFile file, Integer imageSize, List<String> imageTypes, String name){
        if(file == null || file.isEmpty()){
            String message = "上传" + name + "失败，请选择您要上传的文件！";
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_EMPTY, message);
        }

        long size = file.getSize();
        if(size > imageSize * 1024 * 1024){
            String message = "上传" + name + "失败，不允许使用超过" + imageSize + "MB的图片文件！";
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_EXCEED_MAX_SIZE, message);
        }

        String contentType = file.getContentType();
        if(!imageTypes.contains(contentType)){
            String message = "上传" + name + "失败，请使用以下类型的图片文件：" + imageTypes;
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_INVALID_TYPE, message);
        }

    }

    /**
     * 保存图片并返回结果
     * @param file 图片
     * @param imageDir 头像根路径
     * @return 保存结果
     * @throws Throwable
     */
    private UploadResult saveImage(MultipartFile file, String imageDir) throws Throwable{
        //日期目录
        String dirName = sdf.format(new Date());
        File uploadDir = new File(baseDir+imageDir, dirName);
        if(!uploadDir.exists()){
            uploadDir.mkdirs();
        }

        //文件名转换、并保存
        String originalFilename = file.getOriginalFilename();
        String newFileName = UUID.randomUUID().toString();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String newFullFileName = newFileName+suffix;
        File newFile = new File(uploadDir, newFullFileName);
        file.transferTo(newFile);

        //整理返回结果
        String url = new StringBuilder()
                .append(host).append(imageDir)
                .append(dirName).append(newFullFileName).toString();

        UploadResult uploadResult = new UploadResult();
        uploadResult.setUrl(url).setFileName(newFullFileName)
                .setContentType(file.getContentType()).setFileSize(file.getSize());

        return uploadResult;
    }

    /**
     * 删除图片
     * @param url
     * @param imageDir
     */
    private void removeImage(String url, String imageDir){
        int index = url.indexOf(imageDir);
        String newUrl = baseDir + url.substring(index);
        try {
            new File(newUrl).delete();
        } catch (Exception e) {
           log.warn("出现文件未找到异常,文件路径={}", newUrl);
        }
    }
}


















